package com.skyolder.crutch.word;

import java.util.HashMap;

import com.skyolder.crutch.word.token.IdentifierToken;
import com.skyolder.crutch.word.token.KeyWordToken;
import com.skyolder.crutch.word.token.StringToken;
import com.skyolder.crutch.word.token.SymbolToken;
import com.skyolder.crutch.word.token.Token;
import com.skyolder.crutch.word.token.raw.RawToken;
import com.skyolder.crutch.word.types.KeyWordType;
import com.skyolder.crutch.word.types.SymbolType;
import com.skyolder.crutch.word.types.RawTokenType;

public class TokenBuilder {
	private static HashMap<String, SymbolToken> symbolMap = new HashMap<String, SymbolToken>();
	private static HashMap<String, KeyWordToken> keywordMap = new HashMap<String, KeyWordToken>();
	static {
		/**
		 * LBRACKET,RBRACKET,LBRACE,RBRACE,LSQUARE,RSQUARE, //(){} []
		 * ADD,STAR,SUB,DIVISION,PERCENT, //+* - / %
		 * EXCLAMATORY,AT,WELL,DALLAR,AND,OR,REVERSE,// ! @ # $ & |~
		 * ASSIGN,EQUAL,GREAT,SMALL,GREATE,SMALLE, //= == > < >= <=
		 * SQUOTATION,DQUOTATION,BACKQUOTE,//' " ` SEMICOLON //;
		 */
		symbolMap.put("(", new SymbolToken(SymbolType.LBRACKET));
		symbolMap.put(")", new SymbolToken(SymbolType.RBRACKET));
		symbolMap.put("{", new SymbolToken(SymbolType.LBRACE));
		symbolMap.put("}", new SymbolToken(SymbolType.RBRACE));
		symbolMap.put("[", new SymbolToken(SymbolType.LSQUARE));
		symbolMap.put("]", new SymbolToken(SymbolType.RSQUARE));

		symbolMap.put("+", new SymbolToken(SymbolType.ADD));
		symbolMap.put("*", new SymbolToken(SymbolType.STAR));
		symbolMap.put("-", new SymbolToken(SymbolType.SUB));
		symbolMap.put("/", new SymbolToken(SymbolType.DIVISION));
		symbolMap.put("%", new SymbolToken(SymbolType.PERCENT));
		symbolMap.put("\\", new SymbolToken(SymbolType.SLASH));

		symbolMap.put("!", new SymbolToken(SymbolType.EXCLAMATORY));
		symbolMap.put("@", new SymbolToken(SymbolType.AT));
		symbolMap.put("#", new SymbolToken(SymbolType.WELL));
		symbolMap.put("$", new SymbolToken(SymbolType.DOLLAR));
		symbolMap.put("&", new SymbolToken(SymbolType.AND));
		symbolMap.put("|", new SymbolToken(SymbolType.OR));
		symbolMap.put("~", new SymbolToken(SymbolType.REVERSE));

		symbolMap.put("=", new SymbolToken(SymbolType.ASSIGN));
		symbolMap.put("==", new SymbolToken(SymbolType.EQUAL));
		symbolMap.put(">", new SymbolToken(SymbolType.GREAT));
		symbolMap.put("<", new SymbolToken(SymbolType.SMALL));
		symbolMap.put(">=", new SymbolToken(SymbolType.GREATE));
		symbolMap.put("<=", new SymbolToken(SymbolType.SMALLE));
		symbolMap.put("~", new SymbolToken(SymbolType.REVERSE));

		symbolMap.put("'", new SymbolToken(SymbolType.SQUOTATION));
		symbolMap.put("\"", new SymbolToken(SymbolType.DQUOTATION));
		symbolMap.put("`", new SymbolToken(SymbolType.BACKQUOTE));

		symbolMap.put("?", new SymbolToken(SymbolType.QUESTION));
		symbolMap.put(":", new SymbolToken(SymbolType.COLON));
		symbolMap.put("^", new SymbolToken(SymbolType.INVOLUTION));

		symbolMap.put(";", new SymbolToken(SymbolType.SEMICOLON));
		
		symbolMap.put(",", new SymbolToken(SymbolType.COMMA));

	}
	/**
	 * 	IF,ELIF,ELSE,FOR,WHILE,VAR,FUNCTION,
	INT,LONG,DOUBLE,STRING,NULL,BOOL,BYTE,CHAR,VOID,
	GLOBAL,INCLUDE,NAMESPACE,
	RETURN,CONTINUE,BREAK
	 */
	static {
		keywordMap.put("if", new KeyWordToken( KeyWordType.IF));
		keywordMap.put("elif", new KeyWordToken( KeyWordType.ELIF));
		keywordMap.put("else", new KeyWordToken( KeyWordType.ELSE));
		keywordMap.put("for", new KeyWordToken( KeyWordType.FOR));
		keywordMap.put("while",new KeyWordToken(  KeyWordType.WHILE));
		keywordMap.put("var", new KeyWordToken( KeyWordType.VAR));
		keywordMap.put("function", new KeyWordToken( KeyWordType.FUNCTION));
		keywordMap.put("int",new KeyWordToken(  KeyWordType.INT));
		keywordMap.put("long",new KeyWordToken(  KeyWordType.LONG));
		keywordMap.put("double",new KeyWordToken(  KeyWordType.DOUBLE));
		keywordMap.put("string",new KeyWordToken(  KeyWordType.STRING));
		keywordMap.put("null",new KeyWordToken(  KeyWordType.NULL));
		keywordMap.put("bool",new KeyWordToken(  KeyWordType.BOOL));
		keywordMap.put("byte",new KeyWordToken(  KeyWordType.BYTE));
		keywordMap.put("char",new KeyWordToken(  KeyWordType.CHAR));
		keywordMap.put("void",new KeyWordToken(  KeyWordType.VOID));
		keywordMap.put("global",new KeyWordToken(  KeyWordType.GLOBAL));
		keywordMap.put("include",new KeyWordToken(  KeyWordType.INCLUDE));
		keywordMap.put("namespace",new KeyWordToken(  KeyWordType.NAMESPACE));
		keywordMap.put("return",new KeyWordToken(  KeyWordType.RETURN));
		keywordMap.put("continue",new KeyWordToken(  KeyWordType.CONTINUE));
		keywordMap.put("break",new KeyWordToken(  KeyWordType.BREAK));
	}

	public static Token build(RawToken rawToken) {
		if (rawToken.getTokenType() == RawTokenType.KEYWORD) {
			return buildKeyWord(rawToken);
		}
		if (rawToken.getTokenType() == RawTokenType.SYMBOL) {
			return buildSymbol(rawToken);
		}
		if (rawToken.getTokenType() == RawTokenType.STRING) {
			return buildString(rawToken);
		}
		if (rawToken.getTokenType() == RawTokenType.IDENTIFIER) {
			return buildIdentifier(rawToken);
		}
		return null;
	}

	private static Token buildIdentifier(RawToken rawToken) {
		if (rawToken.getWord() == null) {
			return null;
		}
		IdentifierToken identifierToken = new IdentifierToken(rawToken.getWord());
		return identifierToken;
	}

	protected static Token buildString(RawToken rawToken) {
		StringToken stringToken = new StringToken(rawToken.getWord());
		return stringToken;
	}

	protected static Token buildSymbol(RawToken rawToken) {
		if (rawToken.getWord() == null) {
			return null;
		}
		SymbolToken symbolToken = symbolMap.get(rawToken.getWord());
		return symbolToken;
	}

	protected static Token buildKeyWord(RawToken rawToken) {
		KeyWordToken token=keywordMap.get(rawToken.getWord());
		if(token==null){
			return null;
		}
		return token;
	}
}
